Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixing Java field access #1862

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open

Fixing Java field access #1862

wants to merge 4 commits into from

Conversation

oxisto
Copy link
Member

@oxisto oxisto commented Nov 21, 2024

This PR consists of a major overhaul of Java reference and member expression parsing. It removes a LOT of old weird legacy code that was full of weird things.

It also introduces a new Java-specific pass, that takes care of deciding when a member access is actually static or not. This might be something that we could decide to adapt for other/all languages (maybe also tied to the discussion in #1863).

It also contains some adjustments to the import system, more specifically when the importedSymbols field is populated. This might have implications for other languages and if wanted I can extract this into a separate PR.

@oxisto
Copy link
Member Author

oxisto commented Nov 21, 2024

Blocked by #1586

@oxisto oxisto added the blocked Blocked by an external factor label Nov 21, 2024
Copy link

codecov bot commented Nov 21, 2024

Codecov Report

Attention: Patch coverage is 82.05128% with 14 lines in your changes missing coverage. Please review.

Project coverage is 77.07%. Comparing base (e62d7af) to head (0494bdb).

Files with missing lines Patch % Lines
...n/de/fraunhofer/aisec/cpg/passes/SymbolResolver.kt 16.66% 4 Missing and 1 partial ⚠️
...in/de/fraunhofer/aisec/cpg/passes/JavaExtraPass.kt 70.58% 0 Missing and 5 partials ⚠️
...n/de/fraunhofer/aisec/cpg/passes/ImportResolver.kt 85.71% 0 Missing and 2 partials ⚠️
...raunhofer/aisec/cpg/frontends/java/JavaLanguage.kt 60.00% 1 Missing and 1 partial ⚠️
Additional details and impacted files
Files with missing lines Coverage Δ
...tlin/de/fraunhofer/aisec/cpg/frontends/Language.kt 92.24% <100.00%> (+0.49%) ⬆️
...lin/de/fraunhofer/aisec/cpg/passes/TypeResolver.kt 95.83% <100.00%> (+0.18%) ⬆️
...s/kotlin/de/fraunhofer/aisec/cpg/test/TestUtils.kt 71.27% <ø> (ø)
...ofer/aisec/cpg/frontends/java/ExpressionHandler.kt 78.09% <100.00%> (+4.87%) ⬆️
...r/aisec/cpg/frontends/java/JavaLanguageFrontend.kt 70.46% <100.00%> (-4.22%) ⬇️
...n/de/fraunhofer/aisec/cpg/passes/ImportResolver.kt 89.65% <85.71%> (-0.46%) ⬇️
...raunhofer/aisec/cpg/frontends/java/JavaLanguage.kt 84.09% <60.00%> (-3.09%) ⬇️
...n/de/fraunhofer/aisec/cpg/passes/SymbolResolver.kt 86.62% <16.66%> (-1.34%) ⬇️
...in/de/fraunhofer/aisec/cpg/passes/JavaExtraPass.kt 70.58% <70.58%> (ø)

... and 3 files with indirect coverage changes

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@oxisto oxisto removed the blocked Blocked by an external factor label Nov 28, 2024
@oxisto oxisto marked this pull request as ready for review November 28, 2024 14:05
@oxisto oxisto added the java Related to Java language parsing label Nov 28, 2024
Copy link
Contributor

@KuechA KuechA left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fail to understand most of the changes since the old code is hard to understand and the new code requires in-depth knowledge and understanding of the java parser and frontend which I do not have. However, I have some nits which should already be resolved and may support subsequent more detailed reviews.

@@ -209,7 +209,7 @@ open class SymbolResolver(ctx: TranslationContext) : ComponentPass(ctx) {
// Preparation for a future without legacy call resolving. Taking the first candidate is not
// ideal since we are running into an issue with function pointers here (see workaround
// below).
var wouldResolveTo = ref.candidates.singleOrNull()
var wouldResolveTo = ref.candidates.firstOrNull()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change does no longer account for ambiguities. The old code with singleOrNull() prefers not to resolve anything if it's not sure about the candidate. I think this was also intended, wasn't it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was semi-intended. I am ok with the old behavior, but we should at least

  1. have a warning if we do not resolve it
  2. forward the decision to the Language. In Java it is possible to have an ambiguity here if you statically import a field and a function and both can have the same name and end up in candidates. I need to deal with that here

val fieldRef = findByUniquePredicate(refs) { "field" == it.code }
val getSuperField = findByUniqueName(methods, "getSuperField")
refs = getSuperField.allChildren<MemberExpression>()
val superFieldRef = findByUniquePredicate(refs) { "super.field" == it.code }
assertTrue(fieldRef.base is Reference)
assertRefersTo(fieldRef.base, getField.receiver)
// See https://github.com/Fraunhofer-AISEC/cpg/issues/1863.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see how this relates to the case of java.

// See https://github.com/Fraunhofer-AISEC/cpg/issues/1863.
// We only have a regular call expression here, if we do not resolve anything else in the
// frontend
/*assertTrue(fieldRef.base is Reference)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

commented out code. -> Remove or fix. What do we expect?

@@ -889,3 +658,21 @@ class ExpressionHandler(lang: JavaLanguageFrontend) :
}
}
}

fun ResolvedFieldDeclaration.toFieldAccessExpr(expr: NameExpr): FieldAccessExpr {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documentation missing

// }
val name = this.parseName(nameExpr.nameAsString)
return try {
// Try to resolve it. We will remove this in a future where we do not really in the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the TODO of this method resolved? If so, please delete it.

Also, please document the method according to the new standards: #1683 (comment)

This sentence is broken

?: newProblemExpression("Could not parse base")
}
var fieldType: Type?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please document the method according to the new standards: #1683 (comment)


@DependsOn(TypeResolver::class)
@ExecuteBefore(SymbolResolver::class)
class JavaExtraPass(ctx: TranslationContext) : TranslationUnitPass(ctx) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documentation missing for this whole file

@oxisto
Copy link
Member Author

oxisto commented Dec 18, 2024

I fail to understand most of the changes since the old code is hard to understand and the new code requires in-depth knowledge and understanding of the java parser and frontend which I do not have. However, I have some nits which should already be resolved and may support subsequent more detailed reviews.

Agreed. I will extract the remaining changes that are not Java-specific to extra PRs (#1908 and #1909)

…t of candidates

This adds a new function `Language.bestViableReferenceCandidate` which takes the old implementation as a default behaviour.
…tion`

This introduces a new extension function `ImportDeclaration.updateImportedSymbols`. The idea behind that is that we might need to update the `importedSymbols` of an import declaration, if the symbols that "live" in the associated namespace change. This is mainly the case once we infer records out of known `Type` nodes. Therefore, the type resolver will update all the imported symbols before executing all the remaining passes. This way, the remainder of the passes can access imported symbols that were inferred.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
java Related to Java language parsing
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants